package com.gitee.ly.ymorm.session.defaults;

import com.gitee.ly.ymorm.YmOrmConfig;
import com.gitee.ly.ymorm.exceptions.YmOrmException;
import com.gitee.ly.ymorm.executor.Executor;
import com.gitee.ly.ymorm.mapping.ParamMap;
import com.gitee.ly.ymorm.mapping.YmOrmStatement;
import com.gitee.ly.ymorm.session.SqlSession;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

/**
 * DefaultSqlSession
 */
public class DefaultSqlSession implements SqlSession {

    private final YmOrmConfig configuration;
    private final Executor executor;

    private final boolean autoCommit;

    public DefaultSqlSession(YmOrmConfig configuration, Executor executor, boolean autoCommit) {
        this.configuration = configuration;
        this.executor = executor;
        this.autoCommit = autoCommit;
    }

    @Override
    public List<Map> selectList(String statementId, ParamMap paramMap) {
        try {
            YmOrmStatement ms = configuration.getStatement(statementId);
            return executor.query(ms, paramMap, Map.class);
        } catch (SQLException e) {
            throw new YmOrmException(e);
        }
    }

    @Override
    public <E> List<E> selectList(String statementId, ParamMap paramMap, Class<? extends E> resultType) {
        try {
            YmOrmStatement ms = configuration.getStatement(statementId);
            return executor.query(ms, paramMap, resultType);
        } catch (SQLException e) {
            throw new YmOrmException(e);
        }
    }

    @Override
    public int insert(String statementId, ParamMap paramMap) {
        return update(statementId, paramMap);
    }

    @Override
    public int update(String statementId, ParamMap paramMap) {
        try {
            YmOrmStatement ms = configuration.getStatement(statementId);
            return executor.update(ms, paramMap);
        } catch (SQLException e) {
            throw new YmOrmException(e);
        }
    }

    @Override
    public int delete(String statementId, ParamMap paramMap) {
        return update(statementId, paramMap);
    }

    @Override
    public void close() {
        executor.close(!autoCommit || false);
    }

    @Override
    public void commit() {
        commit(false);
    }

    @Override
    public void commit(boolean force) {
        try {
            executor.commit(!autoCommit || force);
        } catch (Exception e) {
            throw new YmOrmException("Error committing transaction.  Cause: " + e, e);
        }
    }

    @Override
    public void rollback() {
        rollback(false);
    }

    @Override
    public void rollback(boolean force) {
        try {
            executor.rollback(!autoCommit || force);
        } catch (Exception e) {
            throw new YmOrmException("Error rolling back transaction.  Cause: " + e, e);
        }
    }

    @Override
    public YmOrmConfig getConfiguration() {
        return configuration;
    }

    @Override
    public Connection getConnection() {
        try {
            return executor.getTransaction().getConnection();
        } catch (SQLException e) {
            throw new YmOrmException("Error getting a new connection.  Cause: " + e, e);
        }
    }
}
